//
// Created by 张朝辉 on 2023/9/16.
//

#ifndef LEARN1_NFA_H
#define LEARN1_NFA_H

#include <set>
#include <map>
#include <utility>
#include <string>
#include "dfa.h"

class NFA {
private:
    std::set<std::string> state_set;       // 有穷状态集
    std::set<char> char_set;               // 字符集
    std::string start_state;               // 初始状态
    std::set<std::string> final_set;       // 终止状态集
    std::map<std::pair<std::string,char>,std::set<std::string>> rule_table;   // 状态转换表

    static int state_num;      // 状态值，用于新状态的获取

    /*
     * 状态转换函数
     * now_state: 当前的状态, acc_char: 接收的字符
     */
    auto state_transition(std::string now_state,char acc_char) -> std::set<std::string>;

    /*
     * 获取某个状态的ε闭包
     */
    auto getEClosure(std::string state) -> std::set<std::string>;

    /*
     * 获取某个状态集的ε闭包
     */
    auto getSetEClosure(std::set<std::string> stateSet) -> std::set<std::string>;

    /*
     * 获取某一个状态集接收某个字符后转换后的状态集
     */
    auto stateSet_transition(std::set<std::string> s, char c) -> std::set<std::string>;

    /*
     * 扩展状态转换函数
     * now_state: 当前的状态, acc_str: 接收的字符串
     */
    auto extend_state_transition(std::string now_state,std::string acc_str) -> std::set<std::string>;

    /*
     *  递归地获取所有的状态集，每个状态集对应于DFA中的某个状态，并将得到的状态集存入s中,s1为初始状态集
     */
    auto getAllStateSet(std::set<std::set<std::string>> &s,std::set<std::string> s1) -> void ;

    /*
     *  判断两个集合是否有交集
     */
    auto setIntersectionIsEmpty(std::set<std::string> s1,std::set<std::string> s2) -> bool;

    /*
     * 获取一个新的状态
     */
    auto static getNewState() -> std::string;

    /*
     * 正则表达式为单个字符的情况下将其转换为NFA
     */
    auto static singleChar2NFA(char ch) -> NFA;

    /*
     * 合并两个NFA，返回一个新的NFA
     */
    auto static combineNFA(NFA n1,NFA n2,char op) -> NFA;

    /*
     * 为某个NFA添加repeat功能
     */
    auto static addStartOp(NFA nfa) -> NFA;

    /*
     * 返回两个算符的优先级
     */
    auto static operatorPriority(char op1,char op2) ->char;

public:
    // 构造函数
    NFA(std::set<std::string> state_set,std::set<char> char_set,std::string start_state,std::set<std::string> final_set,std::map<std::pair<std::string,char>,std::set<std::string>> rule_table);

    /*
     * 判断某个字符串能否被此NFA所接受
     */
    auto isAccept_str(std::string str) -> bool;

    /*
     * 子集构造法将一个NFA转换为与之等价的DFA
     */
    auto NFA2DFA() -> DFA;

    /*
     * 将一个正则表达式转换为NFA，参数正则表达式re应当是一个正则表达式的正确表示方式，本函数不检查正则表达式的正确性
     * 参数正则表达式应当是不省略连接符号.的，否则无法正常识别，应将"ab"书写为"a.b"
     */
    auto static Re2NFA(std::string re) -> NFA;

    /*
     * 打印DFA的相关信息
     */
    auto description() -> void;
};


#endif //LEARN1_NFA_H
